#ifndef __SEMANTIC_H__
#define __SEMANTIC_H__
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<queue>
#include<unordered_set>
#include<unordered_map>
#include<algorithm>
#include<stack>

#include "semantic.h"
using namespace std;
/*
	所有结构体放在这里了
*/
struct table_item{
    string w_name;// 
    int w_kind;// 1 identifier 2 number const 
    int w_type;
    int w_val;
    int w_addr;
    table_item():w_kind(0), w_type(0),w_val(0),w_addr(0) {}
    table_item(int addr) : w_kind(0), w_type(0),w_val(0),w_addr(addr) {}
};
struct attribute{
	struct type1{// D L
		int type;// 1: int 2: float
		int width;//   4      8
	}stateType;
	struct type2{// id E F T
		int type;// 1: int 2: float
		string addr;
	}assignType;
	struct type3{  // S C   控制语句 布尔语句
		int instr; // 指令序号
		vector<int> nextList;
		vector<int> trueList;
		vector<int> falseList;
	}controlType;
};
struct Symbol //文法符号
{
	string name; //符号关键字名 (if-else-id-digist....)
	int type;    //0 终结符号 1 非终结符号
	// string name2;//符号具体名字
	/*
		语义分析需要文法符号增加一些属性如下
		1. 继承属性
		2. 综合属性
		@采用共用体存储节省空间 但是采用共用体报很多错，暂时选用结构体
	*/
	attribute attr;

	friend bool operator== (Symbol s1,Symbol s2){ // 重载符号相等
		return s1.name==s2.name;
	}
	friend bool operator!= (Symbol s1,Symbol s2){ // 重载符号相等
		return s1.name!=s2.name;
	}
};

struct myHashFuc
{
	size_t operator()(const Symbol &key) const
	{
		return hash<string>()(key.name);
	}
};

struct ProductionExpression // 产生式
{
	Symbol left;            // 产生式左部
	vector<vector<Symbol> > rights;  // 产生式右部
	// 左部可能有多个产生式，所以用两重vector来存储
};

struct Item // 项集中的一个项
{
	int wrapperidx; // 点对应exps 第一层的下标
	int expidx;     // 点对应exps 第二层的下标
	int pos;        // 点在产生式中的位置 (0 位最左边)
	Item(int w,int e,int p) : wrapperidx(w), expidx(e),pos(p){}
};

struct Direction
{
	int state;    // 转移到的方向
	string name;  // 接受的符号
	Direction(int s,string n) : state(s), name(n){}
};
struct Items // 项集
{
	int id;                     // 项集编号
	vector<Item> kernelItems;   // 项集中的内核项
	vector<Item> nonKernelItems;// 项集中的非内核项
	vector<Direction> directions;     //项集所指的其他项的下标
    // 重载相等运算符
    friend bool operator== (Items n1, Items n2) // 项集相等保证内核项相同即可
    {
        if (n1.kernelItems.size()!=n2.kernelItems.size()){
        	return false;
        }
        const int n = n1.kernelItems.size();
        vector<bool> visited(n,false);
        for (int i = 0;i<n;++i){
        	bool flag = false;
        	for (int j = 0;j<n;++j){
        		if (!visited[j] && n1.kernelItems[i].wrapperidx==n2.kernelItems[j].wrapperidx
        						&& n1.kernelItems[i].expidx==n2.kernelItems[j].expidx
        						&& n1.kernelItems[i].pos==n2.kernelItems[j].pos){
        			visited[j] = true;
        			flag = true;
        		}
        	}
        	if (!flag) return false;
        }
        return true;
    }
};

struct Act
{
	int type; // 0 移入 1规约
	int state;// 移入进入哪个状态 or 规约对应表达式的第一个编号
	int expidx; //规约对应表达式的第二个编号
};

void semanticAnalysis(int expid,vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);

/*
	下面是根据文法定义的语义动作,LR语法分析器，最后规约的时候执行。
	如果是L属性需要在产生式中间做出动作，则加入空产生式来进行解决
	这些函数并不是都做事
*/

void func01(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func02(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func03(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func04(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func05(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func06(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func07(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func08(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func09(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func10(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func11(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func12(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func13(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func14(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func15(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func16(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func17(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func18(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func19(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func20(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func21(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func22(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func23(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func24(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func25(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func26(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func27(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func28(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func29(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func30(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func31(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);

void func32(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func33(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func34(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func35(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func36(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);
void func37(vector<ProductionExpression> &exps,stack<Symbol> &symStack,vector<table_item> &table,Symbol &sym);

//...

#endif